Skip to content

feat(mcp): /mcp disable / enable + disabled lifecycle (Stage C1 of #105)#108

Merged
esengine merged 1 commit intomainfrom
feat/mcp-disable-enable
May 2, 2026
Merged

feat(mcp): /mcp disable / enable + disabled lifecycle (Stage C1 of #105)#108
esengine merged 1 commit intomainfrom
feat/mcp-disable-enable

Conversation

@esengine
Copy link
Copy Markdown
Owner

@esengine esengine commented May 2, 2026

Stage C1 of #105.

I'm splitting the original "Stage C" into two PRs to keep review tractable:

  • C1 (this PR) — config-persisted disable/enable + ○ disabled lifecycle line
  • C2 (next)/mcp reconnect <name> (live teardown), p95 latency tracker, slow-server toast

What

Lets a user keep a flaky server in their config but skip it on launch:

$ reasonix chat --mcp 'notion=...' --mcp 'linear=...'
⌘ MCP · notion          ↻ handshake…
⌘ MCP · notion          ✓ connected    12 tools · 142ms
⌘ MCP · linear          ○ disabled     via /mcp disable linear

Inside a session:

> /mcp disable notion
▸ notion disabled — takes effect on next launch. /mcp enable notion to revert.

> /mcp enable notion
▸ notion re-enabled — takes effect on next launch.

Touch

  • src/config.tsmcpDisabled?: string[] on ReasonixConfig. Backwards-compatible (missing field reads as empty set).
  • src/cli/ui/mcp-lifecycle.tsdisabled state added to the formatter union; prints ○ disabled via /mcp disable <name>.
  • src/cli/commands/chat.tsx + src/cli/commands/run.ts — read disabled set at startup; skip the bridge for matching named servers and emit the disabled lifecycle line in their place. Anonymous servers (no name=) aren't toggleable by design.
  • src/cli/ui/slash/handlers/mcp.ts — first-arg dispatch:
    • disable <name> writes name into mcpDisabled, idempotent
    • enable <name> removes from the array; deletes the field entirely when the last entry clears (keeps configs tidy)
    • text / no-arg paths unchanged
    • Unknown names produce a "Known: …" hint listing the valid set
  • tests/mcp-lifecycle.test.ts — disabled-state snapshot
  • tests/slash.test.ts — 6 cases for persistence + edge cases, isolated via HOME=tmp per the existing pattern

Test plan

  • npm run verify passes locally (1745 tests, lint, typecheck, build)
  • disable is idempotent; enable clears the field when the array empties
  • Unknown name rejected with the list of valid ones
  • Eyeball: launch with two MCP servers, /mcp disable <name>, restart, confirm the ○ disabled line appears in startup output

Stage C1 of #105 (Stage C split into C1 = persistence side here, C2
= live reconnect + slow toast next).

Add a config-persisted disable list and the corresponding `○ disabled`
lifecycle line so users can keep a flaky server in their config but
skip it on launch.

Touch:

- `src/config.ts` — new `mcpDisabled?: string[]` on ReasonixConfig.
  Backwards-compatible: existing configs ignore it.
- `src/cli/ui/mcp-lifecycle.ts` — `disabled` state added to the
  formatter, prints `○ disabled     via /mcp disable <name>`.
- `src/cli/commands/chat.tsx` + `src/cli/commands/run.ts` — read the
  disabled set on startup; skip the bridge for matching named
  servers and emit the `disabled` lifecycle line in their place.
  Anonymous servers (no `name=`) are not toggleable, by design.
- `src/cli/ui/slash/handlers/mcp.ts` — first-arg dispatch:
  - `disable <name>` writes the name into `mcpDisabled`, idempotent
  - `enable <name>` removes from the array; deletes the field
    entirely when the last entry clears (keeps configs tidy)
  - `text` / no-arg paths unchanged
  Unknown names produce a "Known: …" hint listing the valid set
  (joined from live mcpServers labels + parsed config specs).
- `tests/mcp-lifecycle.test.ts` — disabled-state snapshot
- `tests/slash.test.ts` — six cases: persistence, idempotent
  disable, enable that empties the array, enable that clears the
  field, unknown-name rejection, missing-arg usage line. All
  isolated through `HOME=tmp` per the existing pattern.

Stage C2 (next PR): `/mcp reconnect <name>` (live teardown +
re-handshake), p95 latency tracker, slow-server warn toast.

Closes part of #105.
@esengine esengine merged commit 456cc34 into main May 2, 2026
1 check passed
@esengine esengine deleted the feat/mcp-disable-enable branch May 2, 2026 07:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant